package cn.htsyb.synergy.security.controller;

import cn.htsyb.synergy.model.ApiResult;
import cn.htsyb.synergy.orm.constant.DeleteMode;
import cn.htsyb.synergy.orm.jpa.criterion.OrderExpress;
import cn.htsyb.synergy.orm.jpa.criterion.QueryExpress;
import cn.htsyb.synergy.orm.jpa.model.param.PageParam;
import cn.htsyb.synergy.security.bean.param.SecurityDataAuthorizeParam;
import cn.htsyb.synergy.security.entity.SecurityDataAuthorize;
import cn.htsyb.synergy.security.service.ISecurityDataAuthorizeService;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.constraints.NotNull;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;


/**
 * 数据授权 接口
 * codeMaker at 2020-07-14
 *
 * @author lakeside hubin_yuan.410@hotmail.com
 * @since 2020-07-14
 */
@Slf4j(topic = "security")
@RestController(value = "SecurityDataAuthorizeRestController")
@RequestMapping(value = {"/security/dataAuthorize"})
@Tag(name = "SecurityDataAuthorizeRestController",description ="数据授权接口" )
public class SecurityDataAuthorizeRestController {
    @Autowired
    protected ISecurityDataAuthorizeService securityDataAuthorizeService;
    ObjectMapper objectMapper = new ObjectMapper();

    /**
     * 默认排序
     *
     * @return
     */
    private List<OrderExpress> defaultOrderBy() {
        return new ArrayList<OrderExpress>() {{
            this.add(new OrderExpress("id", OrderExpress.Direction.DESC));
        }};
    }

    /**
     * 添加【我的】条件
     *
     * @return
     */
    private List<QueryExpress> addMineCriterion(List<QueryExpress> searchBys) {
        //searchBys.add(new QueryExpress("created_by", OperatorEnum.EQ,SecurityContextUtil.getCurrentAuthUserId()));
        return searchBys;
    }

    @Operation(summary = "统计数量查询")
    @GetMapping(value = "/count")
    public ApiResult<Long> countSearch(SecurityDataAuthorizeParam securityDataAuthorizeParam) {
        try {
            Long countSize = securityDataAuthorizeService.countAll(addMineCriterion(securityDataAuthorizeParam.searchCriterion()), securityDataAuthorizeParam.filterCriterion());
            return ApiResult.instance(countSize);
        } catch (Exception ex) {
            log.error("统计数量查询", ex);
            return ApiResult.instance(400, ex.getMessage());
        }
    }

    @Operation(summary = "获取对象信息")
    @GetMapping(value = "/{idArr}")
    public ApiResult<SecurityDataAuthorize> findById(@PathVariable @Parameter(description = "记录主键，多个记录使用【,】分割", required = true) List<String> idArr) {
        try {
            if (idArr.size() == 1) {
                SecurityDataAuthorize securityDataAuthorize = securityDataAuthorizeService.findById(idArr.get(0));
                Assert.notNull(securityDataAuthorize, "实体对象不存在");
                return new ApiResult(securityDataAuthorize);
            } else {
                List<SecurityDataAuthorize> securityDataAuthorizeList = securityDataAuthorizeService.findAllByIds(idArr);
                return new ApiResult(securityDataAuthorizeList);
            }
        } catch (Exception ex) {
            log.error("获取对象信息出现错误", ex);
            return ApiResult.instance(400, ex.getMessage());
        }
    }

    @Operation(summary = "分页查询信息")
    @GetMapping(value = "/page")
    @ResponseBody
    public ApiResult<Page<SecurityDataAuthorize>> pageSearch(PageParam pageParam, SecurityDataAuthorizeParam securityDataAuthorizeParam) {
        try {
            List<OrderExpress> orderBys = OrderExpress.parseOrderParam(pageParam.getOrder());
            if (CollectionUtils.isEmpty(orderBys)) {
                orderBys = defaultOrderBy();
            }
            Page<SecurityDataAuthorize> pageResult = securityDataAuthorizeService.findAllPage(
                    addMineCriterion(securityDataAuthorizeParam.searchCriterion()),
                    securityDataAuthorizeParam.filterCriterion(), orderBys, pageParam);
            return ApiResult.instance(pageResult);
        } catch (Exception ex) {
            log.error("分页查询实体出现错误", ex);
            return ApiResult.instance(400, ex.getMessage());
        }
    }

    @Operation(summary = "列表查询信息")
    @GetMapping(value = "/list")
    public ApiResult<Collection<SecurityDataAuthorize>> listSearch(SecurityDataAuthorizeParam securityDataAuthorizeParam) {
        try {
            Collection<SecurityDataAuthorize> listResult = securityDataAuthorizeService.findAllList(
                    addMineCriterion(securityDataAuthorizeParam.searchCriterion()),
                    securityDataAuthorizeParam.filterCriterion(), defaultOrderBy());
            return new ApiResult(listResult);
        } catch (Exception ex) {
            log.error("查询实体列表出现错误", ex);
            return ApiResult.instance(400, ex.getMessage());
        }
    }

    @PreAuthorize("hasAnyAuthority({'security:dataAuthorize:add','security:dataAuthorize:edit'})")
    @Operation(summary = "批量保存实体信息（全量插入）", description = "批量保存实体信息（更新面向实体，全量插入）")
    @PostMapping(value = "/save")
    public ApiResult<?> saveBatch(@RequestBody @NotNull JsonNode filedJsonNode) {
        try {
            if (filedJsonNode.isArray()) {
                List<SecurityDataAuthorize> securityDataAuthorizeList = objectMapper.readValue(filedJsonNode.toString(), new TypeReference<List<SecurityDataAuthorize>>() {
                });
                return ApiResult.instance(securityDataAuthorizeService.saveAllEntity(securityDataAuthorizeList));
            } else {
                SecurityDataAuthorize securityDataAuthorize = objectMapper.readValue(filedJsonNode.toString(), SecurityDataAuthorize.class);
                return ApiResult.instance(securityDataAuthorizeService.saveEntity(securityDataAuthorize));
            }
        } catch (Exception ex) {
            log.error("保存实体信息出现错误", ex);
            return ApiResult.instance(400, ex.getMessage());
        }
    }

    @PreAuthorize("hasAuthority('security:dataAuthorize:edit')")
    @Operation(summary = "批量更新实体部分字段信息", description = "批量更新实体的字段信息(更新面向字段，未传字段不更新))")

    @PutMapping(value = "/{idArr}")
    public ApiResult<List<SecurityDataAuthorize>> patchBatch(
            @PathVariable @Parameter(description = "记录主键，多个记录使用【,】分割", required = true) List<String> idArr,
            @NotNull @RequestBody JsonNode filedJsonNode) {
        try {
            Assert.isTrue(!filedJsonNode.has("id"), "更新字段中不能存在主键编号字段");
            Assert.isTrue(!filedJsonNode.isArray(), "不能使用数组设置更新字段");
            List<SecurityDataAuthorize> securityDataAuthorizeList = securityDataAuthorizeService.findAllByIds(idArr);
            for (SecurityDataAuthorize securityDataAuthorize : securityDataAuthorizeList) {
                objectMapper.readerForUpdating(securityDataAuthorize).readValue(filedJsonNode);
            }
            securityDataAuthorizeService.saveAllEntity(securityDataAuthorizeList);
            return ApiResult.instance(securityDataAuthorizeList);
        } catch (Exception ex) {
            log.error("更新实体字段信息出现错误", ex);
            return ApiResult.instance(400, ex.getMessage());
        }
    }

    @PreAuthorize("hasAuthority('security:dataAuthorize:del')")
    @Operation(summary = "实体删除")
    @DeleteMapping(value = "/{idArr}")
    public ApiResult<List<String>> deleteBatch(
            @PathVariable @Parameter(description = "记录主键，多个记录使用【,】分割", required = true) List<String> idArr,
            @RequestParam(required = false, defaultValue = "logical") @Parameter(description = "删除模式", required = true) DeleteMode deleteMode) {
        try {
            securityDataAuthorizeService.deleteByIds(idArr, deleteMode);

            return ApiResult.instance(idArr);
        } catch (Exception ex) {
            log.error("实体删除出现错误", ex);
            return ApiResult.instance(400, ex.getMessage());
        }
    }
}
